package gene;

import java.util.ArrayList;
import java.util.Random;

import chromo.Chromosome;
import gates.Gates;

public class Gene {
	
	private Input inputTop, inputLeft;
	private Gates gateRight, gateDown;
	private Input outputRight, outputDown;
	private int row, col;
	public ArrayList<Boolean> outputRightValues = new ArrayList<Boolean>();
	public ArrayList<Boolean> outputDownValues = new ArrayList<Boolean>();
	
	private static Random random = new Random();
	//Creates a gene at a certain place in the gene array using the inputs
	//If it isn't on an edge it will grab the appropriate output from the left or right
	public Gene(int row, int col, ArrayList<Input> inputs, Gene[][] genes) throws ChinkleException{
		this.row = row;
		this.col = col;
		if(col == 0){
			inputLeft = inputs.get(random.nextInt(Chromosome.defaultInputs + 2));
		}
		else{
			inputLeft = genes[row][col-1].getOutputRight();
		}
		if(row == 0){
			inputTop = inputs.get(random.nextInt(Chromosome.defaultInputs + 2));
		}
		else{
			inputTop = genes[row-1][col].getOutputDown();
		}
		gateRight = Gates.getGate();
		gateDown = Gates.getGate();
		Input temp = new Input(inputs.size());
		inputs.add(temp);
		outputRight = temp;
		temp = new Input(inputs.size());
		inputs.add(temp);
		outputDown = temp;
		
	}

	//Sets the outputs of a gene AND adds that value to a list
	public void solve(){
		//TODO took minus 1 off
		if(outputRightValues.size() > Math.pow(2, Chromosome.defaultInputs)-1){
			outputDownValues.clear();
			outputRightValues.clear();
		}
		outputRight.setBool(gateRight.eval(inputLeft.getBool(), inputTop.getBool()));
		outputRightValues.add(gateRight.eval(inputLeft.getBool(), inputTop.getBool()));
		outputDown.setBool(gateDown.eval(inputLeft.getBool(), inputTop.getBool()));
		outputDownValues.add(gateDown.eval(inputLeft.getBool(), inputTop.getBool()));
	}
	public Input getOutputRight() {
		return outputRight;
	}

	public void setOutputRight(Input outputRight) {
		this.outputRight = outputRight;
	}

	public Input getOutputDown() {
		return outputDown;
	}

	public void setOutputDown(Input outputDown) {
		this.outputDown = outputDown;
	}
	//Prints genes
	public String toString(){
		return "Row " + row + " Col " + col +"\nInputTop " + inputTop + " InputLeft " + inputLeft +"\nGateRight " + gateRight + " GateDown " + gateDown + "\nOutputRight "+ outputRight + " OutputDown " + outputDown + "\nRight: "+ outputRightValues + "\nDown: " + outputDownValues + "\n";
				
	}

	public void mutate() throws ChinkleException {
		gateRight = Gates.getGate();
		gateDown = Gates.getGate();
		
		outputDownValues.clear();
		outputRightValues.clear();
		
	}
}
